/**
 * @file   USB2XXX_CAN_Test.cpp
 * @brief  CAN总线数据收发测试
 * @author wdluo(wdluo@toomoss.com)
 * @version 1.0
 * @date 2022-11-16
 * @copyright Copyright (c) 2022 重庆图莫斯电子科技有限公司
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "usb_device.h"
#include "usb2can.h"
#if _WIN32
#include <windows.h>
#pragma comment(lib,"USB2XXX.lib")
#endif

#define GET_FIRMWARE_INFO   1
#define CAN_MODE_LOOPBACK   0
#define CAN_SEND_MSG        1
#define CAN_GET_MSG         1
#define CAN_GET_STATUS      0
#define CAN_SCH             0

int main(int argc, const char* argv[])
{
#if GET_FIRMWARE_INFO
    DEVICE_INFO DevInfo;
#endif
    int DevHandle[10];
    int SendCANIndex = 0;//0-CAN1,1-CAN2
    int ReadCANIndex = 0;//0-CAN1,1-CAN2
    bool state;
    int ret;
    CAN_MSG CanMsgBuffer[10240];
    int CanNum;
    //打印动态库编译日期
    char dllBuildDateTime[64]={0};
    DEV_GetDllBuildTime(dllBuildDateTime);
    printf("DLL Build Date Time = %s\n",dllBuildDateTime);
    //扫描设备，必须调用
    ret = USB_ScanDevice(DevHandle);
    if(ret <= 0){
        printf("No device connected!\n");
        getchar();
        return 0;
    }else{
        printf("USB_ScanDevice ret=%d\n",ret);
    }
    //打开设备，必须调用
    state = USB_OpenDevice(DevHandle[0]);
    if(!state){
        printf("Open device error!\n");
        return 0;
    }
#if GET_FIRMWARE_INFO
    char FunctionStr[256]={0};
    //获取设备固件相关信息
    state = DEV_GetDeviceInfo(DevHandle[0],&DevInfo,FunctionStr);
    if(!state){
        printf("Get device infomation error!\n");
        return 0;
    }else{
        printf("Firmware Info:\n");
	    printf("Firmware Name:%s\n",DevInfo.FirmwareName);
        printf("Firmware Build Date:%s\n",DevInfo.BuildDate);
        printf("Firmware Version:v%d.%d.%d\n",(DevInfo.FirmwareVersion>>24)&0xFF,(DevInfo.FirmwareVersion>>16)&0xFF,DevInfo.FirmwareVersion&0xFFFF);
        printf("Hardware Version:v%d.%d.%d\n",(DevInfo.HardwareVersion>>24)&0xFF,(DevInfo.HardwareVersion>>16)&0xFF,DevInfo.HardwareVersion&0xFFFF);
    }
#endif
    //获取CAN波特率参数并初始化配置CAN
    CAN_INIT_CONFIG CANConfig;
    ret = CAN_GetCANSpeedArg(DevHandle[0],&CANConfig,500000);
    if(ret != CAN_SUCCESS){
        printf("Get CAN Speed Arg Failed!\n");
        return 0;
    }else{
        printf("Get CAN Speed Arg Success!\n");
    }
#if CAN_MODE_LOOPBACK
    CANConfig.CAN_Mode = 1;//自发自收模式
#else
    CANConfig.CAN_Mode = 0x80;//正常模式并使能CAN总线终端电阻
#endif
    ret = CAN_Init(DevHandle[0],SendCANIndex,&CANConfig);
    if(ret != CAN_SUCCESS){
        printf("Config CAN failed!\n");
        return 0;
    }else{
        printf("Config CAN Success!\n");
    }
    ret = CAN_Init(DevHandle[0],ReadCANIndex,&CANConfig);
    if(ret != CAN_SUCCESS){
        printf("Config CAN failed!\n");
        return 0;
    }else{
        printf("Config CAN Success!\n");
    }
    //配置过滤器，接收所有帧，可以不配置，默认接收所有帧
    CAN_FILTER_CONFIG CANFilter;
    CANFilter.Enable = 1;
    CANFilter.ExtFrame = 0;
    CANFilter.FilterIndex = 0;
    CANFilter.FilterMode = 0;
    CANFilter.ID_IDE = 0;
    CANFilter.ID_RTR = 0;
    CANFilter.ID_Std_Ext = 0x7A7;
    CANFilter.MASK_IDE = 1;
    CANFilter.MASK_RTR = 1;
    CANFilter.MASK_Std_Ext = 0xFFFFFFFF;
    ret = CAN_Filter_Init(DevHandle[0],ReadCANIndex,&CANFilter);
    if(ret != CAN_SUCCESS){
        printf("Config CAN Filter failed!\n");
        return 0;
    }else{
        printf("Config CAN Filter Success!\n");
    }
#if CAN_SEND_MSG
    CAN_MSG CanMsg[5];
    for(int i=0;i<5;i++){
        CanMsg[i].ExternFlag = 0;
        CanMsg[i].RemoteFlag = 0;
        CanMsg[i].ID = i+0x7A7;
        CanMsg[i].DataLen = 8;
        for(int j=0;j<CanMsg[i].DataLen;j++){
            CanMsg[i].Data[j] = j;
        }
    }
    for(int t=0;t<500;t++){
        int SendedNum = CAN_SendMsg(DevHandle[0],SendCANIndex,CanMsg,5);
        if(SendedNum >= 0){
            printf("Success send frames:%d\n",SendedNum);
        }else{
            printf("Send CAN data failed! %d\n",SendedNum);
        }
        CanNum = CAN_GetMsg(DevHandle[0],ReadCANIndex,CanMsgBuffer);
        if(CanNum > 0){
            printf("CanNum = %d\n",CanNum);
            for(int i=0;i<CanNum;i++){
                printf("CanMsg[%d].ID = 0x%08X\n",i,CanMsgBuffer[i].ID);
                printf("CanMsg[%d].TimeStamp = %.4f s\n",i,(CanMsgBuffer[i].TimeStamp|((uint64_t)CanMsgBuffer[i].TimeStampHigh<<32))/10000.0);
                printf("CanMsg[%d].Data = ",i);
                for(int j=0;j<CanMsgBuffer[i].DataLen;j++){
                    printf("%02X ",CanMsgBuffer[i].Data[j]);
                }
                printf("\n");
            }
        }else if(CanNum == 0){
            printf("No CAN data!\n");
        }else{
            printf("Get CAN data error!\n");
        }
        Sleep(100);
    }
#endif
#if CAN_GET_STATUS
    CAN_STATUS CANStatus;
    ret = CAN_GetStatus(DevHandle[0],SendCANIndex,&CANStatus);
    if(ret == CAN_SUCCESS){
        printf("TSR = %08X\n",CANStatus.TSR);
        printf("ESR = %08X\n",CANStatus.ESR);
    }else{
        printf("Get CAN status error!\n");
    }
#endif
    //延时
#ifdef _WIN32
    Sleep(100);
#else
    usleep(100*1000);
#endif
#if CAN_GET_MSG
    for(int t=0;t<1000;t++){
        CanNum = CAN_GetMsg(DevHandle[0],ReadCANIndex,CanMsgBuffer);
        if(CanNum > 0){
            printf("CanNum = %d\n",CanNum);
            for(int i=0;i<CanNum;i++){
                printf("CanMsg[%d].ID = 0x%08X\n",i,CanMsgBuffer[i].ID);
                printf("CanMsg[%d].TimeStamp = %.4f s\n",i,(CanMsgBuffer[i].TimeStamp|((uint64_t)CanMsgBuffer[i].TimeStampHigh<<32))/10000.0);
                printf("CanMsg[%d].Data = ",i);
                for(int j=0;j<CanMsgBuffer[i].DataLen;j++){
                    printf("%02X ",CanMsgBuffer[i].Data[j]);
                }
                printf("\n");
            }
        }else if(CanNum == 0){
            printf("No CAN data!\n");
        }else{
            printf("Get CAN data error!\n");
        }
#ifdef _WIN32
        Sleep(500);
#else
        usleep(500*1000);
#endif
    }
#endif
#if CAN_SCH
    CAN_MSG CanSchMsg[5];
    for(int i=0;i<5;i++){
        CanSchMsg[i].ExternFlag = 0;
        CanSchMsg[i].RemoteFlag = 0;
        CanSchMsg[i].ID = (i<<4)|(i+1);
        CanSchMsg[i].DataLen = 8;
        for(int j=0;j<CanMsg[i].DataLen;j++){
            CanSchMsg[i].Data[j] = j;
        }
        CanSchMsg[i].TimeStamp =10;//֡帧间隔时间，单位为ms
    }
    unsigned char MsgNum[]={5};//调度表里面有5帧数据，只有一个调度表
    unsigned short MsgSendTimes[]={1};//调度表里面的数据只发送一次
    ret = CAN_SetSchedule(DevHandle[0],SendCANIndex,CanSchMsg,MsgNum,MsgSendTimes,1);
    if(ret == CAN_SUCCESS){
        printf("Set CAN Schedule Success!\n");
    }else{
        printf("Set CAN Schedule Failed!\n");
    }
    ret = CAN_StartSchedule(DevHandle[0],SendCANIndex,0,5,1);
    if(ret == CAN_SUCCESS){
        printf("Start CAN Schedule Success!\n");
    }else{
        printf("Start CAN Schedule Failed!\n");
    }
#if _WIN32
    Sleep(100);
#else
    usleep(100*1000);
#endif
    CanNum = CAN_GetMsg(DevHandle[0],ReadCANIndex,CanMsgBuffer);
    if(CanNum > 0){
        printf("CanNum = %d\n",CanNum);
        for(int i=0;i<CanNum;i++){
            printf("CanMsg[%d].ID = 0x%08X\n",i,CanMsgBuffer[i].ID);
            printf("CanMsg[%d].TimeStamp = %.4f s\n",i,(CanMsgBuffer[i].TimeStamp|((uint64_t)CanMsgBuffer[i].TimeStampHigh<<32))/10000.0);
            printf("CanMsg[%d].Data = ",i);
            for(int j=0;j<CanMsgBuffer[i].DataLen;j++){
                printf("%02X ",CanMsgBuffer[i].Data[j]);
            }
            printf("\n");
        }
    }else if(CanNum == 0){
        printf("No CAN data!\n");
    }else{
        printf("Get CAN data error!\n");
    }
    CAN_StopSchedule(DevHandle[0],SendCANIndex);
#endif
    //关闭设备
    USB_CloseDevice(DevHandle[0]);
	return 0;
}

